/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This application is open source and may be redistributed and/or modified   
 * freely and without restriction, both in commericial and non commericial applications,
 * as long as this copyright notice is maintained.
 * 
 * This application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>

#include <osg/Switch>
#include <osgText/Text>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>

#include <iostream>

extern "C" int osgmain();

//using namespace osg;

int osgmain(){
	int argc;
	char* argv[1];
	
	argc=1;
	argv[0]="osg.mod";

	osg::ArgumentParser arguments(&argc,argv);
	
	arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
	arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
	arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
	arguments.getApplicationUsage()->addCommandLineOption("--image <filename>","Load an image and render it on a quad");
	arguments.getApplicationUsage()->addCommandLineOption("--dem <filename>","Load an image/DEM and render it on a HeightField");
	arguments.getApplicationUsage()->addCommandLineOption("--login <url> <username> <password>","Provide authentication information for http file access.");
	
	osgViewer::Viewer viewer(arguments);
	
	// set up the camera manipulators.
	{
	osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
	
	keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
	keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
	keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
	keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
	
	std::string pathfile;
	char keyForAnimationPath = '5';
	while (arguments.read("-p",pathfile))
	{
	osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
	if (apm || !apm->valid()) 
	{
	unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
	keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
	keyswitchManipulator->selectMatrixManipulator(num);
	++keyForAnimationPath;
	}
	}
	viewer.setCameraManipulator( keyswitchManipulator.get() );
	}
	
	// add the state manipulator
	viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
	
	// add the thread model handler
	viewer.addEventHandler(new osgViewer::ThreadingHandler);
	
	// add the window size toggle handler
	viewer.addEventHandler(new osgViewer::WindowSizeHandler);
	
	// add the stats handler
	viewer.addEventHandler(new osgViewer::StatsHandler);
	
	// add the help handler
	//    viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
	
	// add the record camera path handler
	viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
	
	// add the LOD Scale handler
	viewer.addEventHandler(new osgViewer::LODScaleHandler);
	
	// add the screen capture handler
	viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);

	/*
	// load the data
	osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
	if (!loadedModel) 
	{
	std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
	return 1;
	}
	// any option left unread are converted into errors to write out later.
	arguments.reportRemainingOptionsAsUnrecognized();
	// report any errors if they have occurred when parsing the program arguments.
	if (arguments.errors())
	{
	arguments.writeErrorMessages(std::cout);
	return 1;
	}
	// optimize the scene graph, remove redundant nodes and state etc.
	osgUtil::Optimizer optimizer;
	optimizer.optimize(loadedModel.get());	
	viewer.setSceneData( loadedModel.get() );
*/
	
	viewer.realize();	
	return viewer.run();
	
}
